class AuthD::Request
	IPC::JSON.message AddUser, 9 do
		property login      : String
		property password   : String
		property admin      : Bool                     = false
		property email      : String?                  = nil
		property profile    : Hash(String, JSON::Any)? = nil

		def initialize(@login, @password, @admin, @email, @profile)
		end

		def to_s(io : IO)
			super io
			io << " (login: #{@login}, email: #{@email})"
		end

		def handle(authd : AuthD::Service, fd : Int32)
			logged_user = authd.get_logged_user_full? fd
			return Response::ErrorMustBeAuthenticated.new if logged_user.nil?

			logged_user.assert_permission("authd", "*", User::PermissionLevel::Admin)

			if authd.users_per_login.get? @login
				return Response::ErrorAlreadyUsedLogin.new
			end

			# No verification of the user's informations when an admin adds it.
			# No mail address verification.
			if authd.configuration.require_email && @email.nil?
				return Response::ErrorMailRequired.new
			end

			password_hash = authd.hash_password @password

			uid = authd.new_uid

			user = User.new uid, @login, password_hash
			user.contact.email = @email unless @email.nil?
			user.admin         = @admin

			@profile.try do |profile|
				user.profile = profile
			end

			# We consider adding the user as a registration.
			user.date_registration = Time.local

			authd.users << user
			authd.new_uid_commit uid
			Response::UserAdded.new user.to_public
		end
	end
	AuthD.requests << AddUser

	IPC::JSON.message BootstrapFirstAdmin, 13 do
		property login      : String
		property password   : String
		property email      : String?                  = nil
		property profile    : Hash(String, JSON::Any)? = nil

		def initialize(@login, @password, @email, @profile = nil)
		end

		def to_s(io : IO)
			super io
			io << " (login: #{@login}, email: #{email})"
		end

		def handle(authd : AuthD::Service, fd : Int32)
			# Check if there already is a registered user.
			if authd.users.to_a.size > 0
				return Response::ErrorAlreadyUsersInDB.new
			end

			password_hash = authd.hash_password @password

			uid = authd.new_uid

			user = User.new uid, @login, password_hash
			user.contact.email = @email unless @email.nil?
			user.admin         = true

			@profile.try do |profile|
				user.profile = profile
			end

			# We consider adding the user as a registration.
			user.date_registration = Time.local

			authd.users << user
			authd.new_uid_commit uid
			Response::UserAdded.new user.to_public
		end
	end
	AuthD.requests << BootstrapFirstAdmin

	IPC::JSON.message DecodeToken, 14 do
		property token   : String

		def initialize(@token)
		end

		def to_s(io : IO)
			super io
			io << " (token size: #{@token.size})"
		end

		def handle(authd : AuthD::Service, fd : Int32)
			logged_user = authd.get_logged_user_full? fd
			return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
			logged_user.assert_permission("authd", "*", User::PermissionLevel::Read)

			token_payload = AuthD::Token.from_s authd.configuration.secret_key, token
			user = authd.users_per_uid.get? token_payload.uid.to_s
			if user
				Response::User.new user.to_public
			else
				Response::ErrorUserNotFound.new
			end
		end
	end
	AuthD.requests << DecodeToken

	IPC::JSON.message Exit, 248 do
		def initialize
		end

		def to_s(io : IO)
			super io
		end

		def handle(authd : AuthD::Service, fd : Int32)
			logged_user = authd.get_logged_user_full? fd
			return Response::ErrorMustBeAuthenticated.new if logged_user.nil?
			logged_user.assert_permission("authd", "*", User::PermissionLevel::Admin)

			Baguette::Log.warning "exit requested, bye"
			exit 0
		end
	end
	AuthD.requests << Exit
end
